<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="generator" content="AsciiDoc 8.6.6" />
<title>Release notes for Gerrit 2.0.18</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */

/* Default font. */
body {
  font-family: Georgia,serif;
}

/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
  font-family: Arial,Helvetica,sans-serif;
}

body {
  margin: 1em 5% 1em 5%;
}

a {
  color: blue;
  text-decoration: underline;
}
a:visited {
  color: fuchsia;
}

em {
  font-style: italic;
  color: navy;
}

strong {
  font-weight: bold;
  color: #083194;
}

h1, h2, h3, h4, h5, h6 {
  color: #527bbd;
  margin-top: 1.2em;
  margin-bottom: 0.5em;
  line-height: 1.3;
}

h1, h2, h3 {
  border-bottom: 2px solid silver;
}
h2 {
  padding-top: 0.5em;
}
h3 {
  float: left;
}
h3 + * {
  clear: left;
}
h5 {
  font-size: 1.0em;
}

div.sectionbody {
  margin-left: 0;
}

hr {
  border: 1px solid silver;
}

p {
  margin-top: 0.5em;
  margin-bottom: 0.5em;
}

ul, ol, li > p {
  margin-top: 0;
}
ul > li     { color: #aaa; }
ul > li > * { color: black; }

pre {
  padding: 0;
  margin: 0;
}

#author {
  color: #527bbd;
  font-weight: bold;
  font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}

#footer {
  font-size: small;
  border-top: 2px solid silver;
  padding-top: 0.5em;
  margin-top: 4.0em;
}
#footer-text {
  float: left;
  padding-bottom: 0.5em;
}
#footer-badges {
  float: right;
  padding-bottom: 0.5em;
}

#preamble {
  margin-top: 1.5em;
  margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.admonitionblock {
  margin-top: 2.0em;
  margin-bottom: 2.0em;
  margin-right: 10%;
  color: #606060;
}

div.content { /* Block element content. */
  padding: 0;
}

/* Block element titles. */
div.title, caption.title {
  color: #527bbd;
  font-weight: bold;
  text-align: left;
  margin-top: 1.0em;
  margin-bottom: 0.5em;
}
div.title + * {
  margin-top: 0;
}

td div.title:first-child {
  margin-top: 0.0em;
}
div.content div.title:first-child {
  margin-top: 0.0em;
}
div.content + div.title {
  margin-top: 0.0em;
}

div.sidebarblock > div.content {
  background: #ffffee;
  border: 1px solid #dddddd;
  border-left: 4px solid #f0f0f0;
  padding: 0.5em;
}

div.listingblock > div.content {
  border: 1px solid #dddddd;
  border-left: 5px solid #f0f0f0;
  background: #f8f8f8;
  padding: 0.5em;
}

div.quoteblock, div.verseblock {
  padding-left: 1.0em;
  margin-left: 1.0em;
  margin-right: 10%;
  border-left: 5px solid #f0f0f0;
  color: #888;
}

div.quoteblock > div.attribution {
  padding-top: 0.5em;
  text-align: right;
}

div.verseblock > pre.content {
  font-family: inherit;
  font-size: inherit;
}
div.verseblock > div.attribution {
  padding-top: 0.75em;
  text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
  text-align: left;
}

div.admonitionblock .icon {
  vertical-align: top;
  font-size: 1.1em;
  font-weight: bold;
  text-decoration: underline;
  color: #527bbd;
  padding-right: 0.5em;
}
div.admonitionblock td.content {
  padding-left: 0.5em;
  border-left: 3px solid #dddddd;
}

div.exampleblock > div.content {
  border-left: 3px solid #dddddd;
  padding-left: 0.5em;
}

div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }

dl {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
dt {
  margin-top: 0.5em;
  margin-bottom: 0;
  font-style: normal;
  color: navy;
}
dd > *:first-child {
  margin-top: 0.1em;
}

ul, ol {
    list-style-position: outside;
}
ol.arabic {
  list-style-type: decimal;
}
ol.loweralpha {
  list-style-type: lower-alpha;
}
ol.upperalpha {
  list-style-type: upper-alpha;
}
ol.lowerroman {
  list-style-type: lower-roman;
}
ol.upperroman {
  list-style-type: upper-roman;
}

div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
  margin-top: 0.1em;
  margin-bottom: 0.1em;
}

tfoot {
  font-weight: bold;
}
td > div.verse {
  white-space: pre;
}

div.hdlist {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
div.hdlist tr {
  padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
  font-weight: bold;
}
td.hdlist1 {
  vertical-align: top;
  font-style: normal;
  padding-right: 0.8em;
  color: navy;
}
td.hdlist2 {
  vertical-align: top;
}
div.hdlist.compact tr {
  margin: 0;
  padding-bottom: 0;
}

.comment {
  background: yellow;
}

.footnote, .footnoteref {
  font-size: 0.8em;
}

span.footnote, span.footnoteref {
  vertical-align: super;
}

#footnotes {
  margin: 20px 0 20px 0;
  padding: 7px 0 0 0;
}

#footnotes div.footnote {
  margin: 0 0 5px 0;
}

#footnotes hr {
  border: none;
  border-top: 1px solid silver;
  height: 1px;
  text-align: left;
  margin-left: 0;
  width: 20%;
  min-width: 100px;
}

div.colist td {
  padding-right: 0.5em;
  padding-bottom: 0.3em;
  vertical-align: top;
}
div.colist td img {
  margin-top: 0.3em;
}

@media print {
  #footer-badges { display: none; }
}

#toc {
  margin-bottom: 2.5em;
}

#toctitle {
  color: #527bbd;
  font-size: 1.1em;
  font-weight: bold;
  margin-top: 1.0em;
  margin-bottom: 0.1em;
}

div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
  margin-top: 0;
  margin-bottom: 0;
}
div.toclevel2 {
  margin-left: 2em;
  font-size: 0.9em;
}
div.toclevel3 {
  margin-left: 4em;
  font-size: 0.9em;
}
div.toclevel4 {
  margin-left: 6em;
  font-size: 0.9em;
}

span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }

span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }

span.big { font-size: 2em; }
span.small { font-size: 0.6em; }

span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }


/*
 * xhtml11 specific
 *
 * */

tt {
  font-family: monospace;
  font-size: inherit;
  color: navy;
}

div.tableblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.tableblock > table {
  border: 3px solid #527bbd;
}
thead, p.table.header {
  font-weight: bold;
  color: #527bbd;
}
p.table {
  margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
  border-style: none;
}
div.tableblock > table[frame="hsides"] {
  border-left-style: none;
  border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
  border-top-style: none;
  border-bottom-style: none;
}


/*
 * html5 specific
 *
 * */

.monospaced {
  font-family: monospace;
  font-size: inherit;
  color: navy;
}

table.tableblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
thead, p.tableblock.header {
  font-weight: bold;
  color: #527bbd;
}
p.tableblock {
  margin-top: 0;
}
table.tableblock {
  border-width: 3px;
  border-spacing: 0px;
  border-style: solid;
  border-color: #527bbd;
  border-collapse: collapse;
}
th.tableblock, td.tableblock {
  border-width: 1px;
  padding: 4px;
  border-style: solid;
  border-color: #527bbd;
}

table.tableblock.frame-topbot {
  border-left-style: hidden;
  border-right-style: hidden;
}
table.tableblock.frame-sides {
  border-top-style: hidden;
  border-bottom-style: hidden;
}
table.tableblock.frame-none {
  border-style: hidden;
}

th.tableblock.halign-left, td.tableblock.halign-left {
  text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
  text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
  text-align: right;
}

th.tableblock.valign-top, td.tableblock.valign-top {
  vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
  vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
  vertical-align: bottom;
}


/*
 * manpage specific
 *
 * */

body.manpage h1 {
  padding-top: 0.5em;
  padding-bottom: 0.5em;
  border-top: 2px solid silver;
  border-bottom: 2px solid silver;
}
body.manpage h2 {
  border-style: none;
}
body.manpage div.sectionbody {
  margin-left: 3em;
}

@media print {
  body.manpage div#toc { display: none; }
}
</style>
<script type="text/javascript">
/*<![CDATA[*/
var asciidoc = {  // Namespace.

/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////

/* Author: Mihai Bazon, September 2002
 * http://students.infoiasi.ro/~mishoo
 *
 * Table Of Content generator
 * Version: 0.4
 *
 * Feel free to use this script under the terms of the GNU General Public
 * License, as long as you do not remove or alter this notice.
 */

 /* modified by Troy D. Hanson, September 2006. License: GPL */
 /* modified by Stuart Rackham, 2006, 2009. License: GPL */

// toclevels = 1..4.
toc: function (toclevels) {

  function getText(el) {
    var text = "";
    for (var i = el.firstChild; i != null; i = i.nextSibling) {
      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
        text += i.data;
      else if (i.firstChild != null)
        text += getText(i);
    }
    return text;
  }

  function TocEntry(el, text, toclevel) {
    this.element = el;
    this.text = text;
    this.toclevel = toclevel;
  }

  function tocEntries(el, toclevels) {
    var result = new Array;
    var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
    // Function that scans the DOM tree for header elements (the DOM2
    // nodeIterator API would be a better technique but not supported by all
    // browsers).
    var iterate = function (el) {
      for (var i = el.firstChild; i != null; i = i.nextSibling) {
        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
          var mo = re.exec(i.tagName);
          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
          }
          iterate(i);
        }
      }
    }
    iterate(el);
    return result;
  }

  var toc = document.getElementById("toc");
  if (!toc) {
    return;
  }

  // Delete existing TOC entries in case we're reloading the TOC.
  var tocEntriesToRemove = [];
  var i;
  for (i = 0; i < toc.childNodes.length; i++) {
    var entry = toc.childNodes[i];
    if (entry.nodeName == 'div'
     && entry.getAttribute("class")
     && entry.getAttribute("class").match(/^toclevel/))
      tocEntriesToRemove.push(entry);
  }
  for (i = 0; i < tocEntriesToRemove.length; i++) {
    toc.removeChild(tocEntriesToRemove[i]);
  }

  // Rebuild TOC entries.
  var entries = tocEntries(document.getElementById("content"), toclevels);
  for (var i = 0; i < entries.length; ++i) {
    var entry = entries[i];
    if (entry.element.id == "")
      entry.element.id = "_toc_" + i;
    var a = document.createElement("a");
    a.href = "#" + entry.element.id;
    a.appendChild(document.createTextNode(entry.text));
    var div = document.createElement("div");
    div.appendChild(a);
    div.className = "toclevel" + entry.toclevel;
    toc.appendChild(div);
  }
  if (entries.length == 0)
    toc.parentNode.removeChild(toc);
},


/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////

/* Based on footnote generation code from:
 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
 */

footnotes: function () {
  // Delete existing footnote entries in case we're reloading the footnodes.
  var i;
  var noteholder = document.getElementById("footnotes");
  if (!noteholder) {
    return;
  }
  var entriesToRemove = [];
  for (i = 0; i < noteholder.childNodes.length; i++) {
    var entry = noteholder.childNodes[i];
    if (entry.nodeName == 'div' && entry.getAttribute("class") == "footnote")
      entriesToRemove.push(entry);
  }
  for (i = 0; i < entriesToRemove.length; i++) {
    noteholder.removeChild(entriesToRemove[i]);
  }

  // Rebuild footnote entries.
  var cont = document.getElementById("content");
  var spans = cont.getElementsByTagName("span");
  var refs = {};
  var n = 0;
  for (i=0; i<spans.length; i++) {
    if (spans[i].className == "footnote") {
      n++;
      var note = spans[i].getAttribute("data-note");
      if (!note) {
        // Use [\s\S] in place of . so multi-line matches work.
        // Because JavaScript has no s (dotall) regex flag.
        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
        spans[i].innerHTML =
          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
        spans[i].setAttribute("data-note", note);
      }
      noteholder.innerHTML +=
        "<div class='footnote' id='_footnote_" + n + "'>" +
        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
        n + "</a>. " + note + "</div>";
      var id =spans[i].getAttribute("id");
      if (id != null) refs["#"+id] = n;
    }
  }
  if (n == 0)
    noteholder.parentNode.removeChild(noteholder);
  else {
    // Process footnoterefs.
    for (i=0; i<spans.length; i++) {
      if (spans[i].className == "footnoteref") {
        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
        href = href.match(/#.*/)[0];  // Because IE return full URL.
        n = refs[href];
        spans[i].innerHTML =
          "[<a href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
      }
    }
  }
},

install: function(toclevels) {
  var timerId;

  function reinstall() {
    asciidoc.footnotes();
    if (toclevels) {
      asciidoc.toc(toclevels);
    }
  }

  function reinstallAndRemoveTimer() {
    clearInterval(timerId);
    reinstall();
  }

  timerId = setInterval(reinstall, 500);
  if (document.addEventListener)
    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
  else
    window.onload = reinstallAndRemoveTimer;
}

}
asciidoc.install(2);
/*]]>*/
</script>
</head>
<body class="article">
<div id="header">
<h1>Release notes for Gerrit 2.0.18</h1>
<span id="revnumber">version 2.0.18 (from v2.7-rc0-149-g3be717b)</span>
<div id="toc">
  <div id="toctitle">Table of Contents</div>
  <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph"><p>Gerrit 2.0.18 is now available in the usual location:</p></div>
<div class="paragraph"><p><a href="http://code.google.com/p/gerrit/downloads/list">http://code.google.com/p/gerrit/downloads/list</a></p></div>
</div>
</div>
<div class="sect1">
<h2 id="_important_notices">Important Notices</h2>
<div class="sectionbody">
<div class="paragraph"><p>Please ensure you read the following important notices about this release; .18 is a much larger release than usual.</p></div>
<div class="ulist"><ul>
<li>
<p>
OpenID Configuration
</p>
<div class="paragraph"><p>If you use OpenID authentication, the <tt>trusted_external_ids</tt>
table has moved from the database to the local gerrit.config
file.  Please ensure you copy any critical patterns to the
<tt>auth.trustedOpenID</tt> setting in gerrit.config before upgrading
your server.  Failure to set a pattern will allow Gerrit
to trust any OpenID provider.  Refer to <tt>auth.trustedOpenID</tt> in
[<a href="http://gerrit.googlecode.com/svn/documentation/2.0/config-gerrit.html">http://gerrit.googlecode.com/svn/documentation/2.0/config-gerrit.html</a> Configuration] for more details.</p></div>
</li>
<li>
<p>
Caches
</p>
<div class="paragraph"><p>The groups that a user is a member of is no longer stored in the
<tt>groups</tt> cache; it is now part of the <tt>accounts</tt> cache.  If you
use a cron script to update the <tt>account_groups</tt> database table
based upon an external data source (such as LDAP), you will need
to adjust your script to flush the <tt>accounts</tt> cache.
The <tt>diff</tt> cache is no longer written to disk by default.
To enable the disk store again, administrators must explicitly
set <tt>cache.directory</tt> in the gerrit.config file prior to starting
Gerrit.</p></div>
</li>
<li>
<p>
SSH Usernames
</p>
<div class="paragraph"><p>SSH usernames are no longer automatically assigned to the
local part of the user&#8217;s email address.  With 2.0.18, usernames
must also be unique within the database.  These changes were
implemented to resolve a minor potential security issue with
the SSH authentication system.  More details can be found in the
[<a href="http://android.git.kernel.org/?p=tools/gerrit.git;a=commit;h=080b40f7bbe00ac5fc6f2b10a861b63ce63e8add">http://android.git.kernel.org/?p=tools/gerrit.git;a=commit;h=080b40f7bbe00ac5fc6f2b10a861b63ce63e8add</a> commit message].</p></div>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_schema_change">Schema Change</h2>
<div class="sectionbody">
<div class="paragraph"><p><strong>WARNING: This version contains a schema change</strong> (since 2.0.17)</p></div>
<div class="paragraph"><p>Important notes about this schema change:</p></div>
<div class="ulist"><ul>
<li>
<p>
The schema change may be difficult to undo once applied.
</p>
<div class="paragraph"><p>Downgrading could be very difficult once the upgrade has been started.
Going back to 2.0.17 may not be possible.</p></div>
</li>
<li>
<p>
Do not run the schema change while the server is running.
</p>
<div class="paragraph"><p>This upgrade changes the primary keys of several tables, an operation
which shouldn&#8217;t occur while end-users are able to make modifications to
the database.  I <em>strongly</em> suggest a full shutdown, schema upgrade,
then startup approach for this release.
Apply the database specific schema script:</p></div>
</li>
</ul></div>
<div class="listingblock">
<div class="content">
<pre><tt>  java -jar gerrit.war --cat sql/upgrade015_016_part1_postgres.sql | psql reviewdb
  java -jar gerrit.war --cat sql/upgrade015_016_part1_mysql.sql    | mysql reviewdb</tt></pre>
</div></div>
<div class="paragraph"><p>After the upgrade is successful, apply the final script to drop dead tables:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>  java -jar gerrit.war --cat sql/upgrade015_016_part2.sql | psql reviewdb
  java -jar gerrit.war --cat sql/upgrade015_016_part2.sql | mysql reviewdb</tt></pre>
</div></div>
</div>
</div>
<div class="sect1">
<h2 id="_new_bugs">New Bugs</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
Memory leaks during warm restarts
</p>
</li>
</ul></div>
<div class="paragraph"><p>2.0.18 includes [<a href="http://code.google.com/p/google-guice/">http://code.google.com/p/google-guice/</a> Google Guice], which leaves a finalizer thread dangling when the Gerrit web application is halted by the servlet container.  As this thread does not terminate, the web context stays loaded in memory indefinitely, creating a memory leak.  Cold restarting the container in order to restart Gerrit is highly recommended.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_new_features">New Features</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
GERRIT-104  Allow end-users to select their own SSH username
</p>
<div class="paragraph"><p>End users may now select their own SSH username through the web interface.  The username must be unique within a Gerrit server installation.  During upgrades from 2.0.17 duplicate users are resolved by giving the username to the user who most recently logged in under it; other users will need to login through the web interface and select a unique username.  This change was necessary to fix a very minor security bug (see above).</p></div>
</li>
<li>
<p>
Display supported commands when subcommand is not prov&#8230;
</p>
<div class="paragraph"><p>Running <tt>ssh -p 29418 gerrit.example.com gerrit</tt> now lists the complete set of subcommands recognized by the gerrit top level command.  This (slightly) improves discoverability of the remote command execution facilities.</p></div>
</li>
<li>
<p>
Add a Register link in the menu bar when not signed in
</p>
<div class="paragraph"><p>The Register link in the top right shows up on OpenID based sites when the user is not yet signed in.  This should help discoverability of signing into a Gerrit server to establish your account identity.</p></div>
</li>
<li>
<p>
Combine all initial page data into a single object
</p>
</li>
<li>
<p>
Avoid XSRF initialization requests by using one token &#8230;
</p>
<div class="paragraph"><p>An initial XSRF token is now sent as part of the initial HTTP request, and used for all subsequent RPCs from that browser.  This reduces the initial page load time by cutting out a few round trips that previously were used to bootstrap that XSRF token.</p></div>
</li>
<li>
<p>
Redirect /Gerrit#foo to /#foo on the client side
</p>
<div class="paragraph"><p>Gerrit now favors "/#mine" rather than "/Gerrit#mine" for URLs.  Older style URLs will be redirected to the newer style automatically, for the foreseeable future.</p></div>
</li>
<li>
<p>
Sort permissions in project access tab
</p>
</li>
<li>
<p>
Get branches directly from Git rather than database
</p>
</li>
<li>
<p>
Style tab panel headers like our menu bar header
</p>
</li>
<li>
<p>
Narrow tables that don&#8217;t have to be 100% width
</p>
</li>
<li>
<p>
Cleanup display of external ids in the user settings
</p>
<div class="paragraph"><p>A few minor UI nits in the Settings and Admin panels.  The new UI is a bit more consistent with the theme, and formats data in a bit more sane way.  Nothing earth shattering.</p></div>
</li>
<li>
<p>
Make disk cache completely optional
</p>
<div class="paragraph"><p>As noted above in the section about cache changes, the disk cache is now completely optional.</p></div>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_bug_fixes">Bug Fixes</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
GERRIT-5    Remove PatchSetInfo from database and get it always fr&#8230;
</p>
<div class="paragraph"><p>A very, very old bug.  We no longer mirror the commit data into the SQL database, but instead pull it directly from Git when needed.  Removing duplicated data simplifies the data store model, something that is important as we shift from an SQL database to a Git backed database.</p></div>
</li>
<li>
<p>
GERRIT-220  Fix infinite loop in PatchScriptBuilder
</p>
<div class="paragraph"><p>Under somewhat rare conditions web request threads locked up in an infinite loop while obtaining the data necessary to show a side-by-side or unified patch view to a browser.  The loop doesn&#8217;t allocate any memory, or perform any database requests, but it still ties up a database connection and a servlet container request processing thread indefinitely.  We found the bug internally at Google when our Gerrit server load average spiked to 32&#8230; and we had no more connections in our database connection pool, which was also sized at a max of 32 handles.</p></div>
</li>
<li>
<p>
Fix Reviewed-On lines to only include the server URL o&#8230;
</p>
<div class="paragraph"><p>The Reviewed-On lines in cherry-picked commits were duplicating the server URL.</p></div>
</li>
<li>
<p>
Set outgoing email header Content-Transfer-Encoding: 8&#8230;
</p>
<div class="paragraph"><p>Emails are sent in UTF-8, which may have the high bit set.  Thus the transfer encoding must always be set as 8bit, to prevent gateways from potentially discarding the high bits and corrupting the UTF-8 message payload.</p></div>
</li>
<li>
<p>
Ensure OpenID related responses aren&#8217;t cached by proxi&#8230;
</p>
<div class="paragraph"><p>Some OpenID related login responses may have sent HTTP headers which were confusing to proxies, potentially allowing a proxy to cache something it should not have cached.  The headers were clarified to better denote no caching is permitted.</p></div>
</li>
<li>
<p>
Move ChangeApproval to be a child of PatchSet
</p>
<div class="paragraph"><p>The database schema changed, adding <tt>patch_set_id</tt> to the approval object, and renaming the approval table to <tt>patch_set_approvals</tt>.  If you have external code writing to this table, uh, sorry, its broken with this release, you&#8217;ll have to update that code first.  :-\</p></div>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_other_changes">Other Changes</h2>
<div class="sectionbody">
<div class="paragraph"><p>This release is really massive because the internal code moved from some really ugly static data variables to doing almost everything through Guice injection.  Nothing user visible, but code cleanup that needed to occur before we started making additional changes to the system.</p></div>
<div class="ulist"><ul>
<li>
<p>
Start 2.0.18 development
</p>
</li>
<li>
<p>
Remove bad import of HostPageServlet
</p>
</li>
<li>
<p>
Upgrade GWT to 1.7.0
</p>
</li>
<li>
<p>
Update gwt-maven-plugin to 1.1 release
</p>
</li>
<li>
<p>
Remove dead gwt-maven repository
</p>
</li>
<li>
<p>
Stop including gwt-dev JARs in project classpath
</p>
</li>
<li>
<p>
Remove ConvertSystemConfig utility
</p>
</li>
<li>
<p>
Update SSHD to 1.0-r798139
</p>
</li>
<li>
<p>
Update JGit to 0.5.0-57-g4c5eb17
</p>
</li>
<li>
<p>
Replace our RepositoryCache with JGit&#8217;s RepositoryCache
</p>
</li>
<li>
<p>
Make missing project descriptions an empty file
</p>
</li>
<li>
<p>
Remove unused imports.
</p>
</li>
<li>
<p>
Move all service implementations into server side code
</p>
</li>
<li>
<p>
Move RpcConstants out of Common class
</p>
</li>
<li>
<p>
Move the CurrentAccountImpl accessor to Gerrit onModul&#8230;
</p>
</li>
<li>
<p>
Move workflow function access to CategoryFunction class
</p>
</li>
<li>
<p>
Move ChangeDetail.load to strictly server side code
</p>
</li>
<li>
<p>
Move the workflow package to be strictly server side
</p>
</li>
<li>
<p>
Add Guice 2.0 to our dependencies
</p>
</li>
<li>
<p>
Switch web.xml to Guice based injection
</p>
</li>
<li>
<p>
Use Guice injection to pass GerritServer to HttpServle&#8230;
</p>
</li>
<li>
<p>
Use Guice to inject GerritServer into RPC backends
</p>
</li>
<li>
<p>
Move calls to Common.getSchemaFactory to GerritServer&#8230;.
</p>
</li>
<li>
<p>
Create the EncyptedContactStore during servlet startup
</p>
</li>
<li>
<p>
Move OpenID implementation setup to Guice
</p>
</li>
<li>
<p>
Remove more Common.getSchemaFactory invocations to dir&#8230;
</p>
</li>
<li>
<p>
Pass GerritServer down through SSH command factory
</p>
</li>
<li>
<p>
Pass GerritServer instance down through the push queue
</p>
</li>
<li>
<p>
Use Guice to setup the FileTypeRegistery singleton
</p>
</li>
<li>
<p>
Delete unnecessary GerritCacheControlFilter
</p>
</li>
<li>
<p>
Remove pointless Srv subclasses of GerritJsonServlet
</p>
</li>
<li>
<p>
Refactor FileTypeRegsitery to be an interface
</p>
</li>
<li>
<p>
Let Guice inject the ContactStore implementation
</p>
</li>
<li>
<p>
Remove dependency on gwtexpui, gwtjsonrpc and gwtorm p&#8230;
</p>
</li>
<li>
<p>
Use Guice to bring up the SSH daemon and its configura&#8230;
</p>
</li>
<li>
<p>
Remove unnecessary GerritServer field in Receive comma&#8230;
</p>
</li>
<li>
<p>
Move PushQueue and ReplicationQueue to singletons mana&#8230;
</p>
</li>
<li>
<p>
Get rid of the GerritServer static singleton
</p>
</li>
<li>
<p>
Provide SchemFactory ReviewDb by Guice and not Gerrit&#8230;
</p>
</li>
<li>
<p>
Get the SystemConfig from Guice rather than GerritServ&#8230;
</p>
</li>
<li>
<p>
Merge change 10823
</p>
</li>
<li>
<p>
Inject the site path configuration setting directly
</p>
</li>
<li>
<p>
Use FileBasedConfig Config rather than RepositoryConfig
</p>
</li>
<li>
<p>
Correct copyright dates in SitePath support to be 2009
</p>
</li>
<li>
<p>
Load gerrit.config through Guice injection
</p>
</li>
<li>
<p>
Refactor outgoing email to be constructed by Guice
</p>
</li>
<li>
<p>
Move contact store configuration off GerritServer
</p>
</li>
<li>
<p>
Configure Eclipse projects to cleanup trailing whitesp&#8230;
</p>
</li>
<li>
<p>
Move PatchSetPublishDetail.load() to server side and i&#8230;
</p>
</li>
<li>
<p>
Hide GerritServer.getGerritConfig and use Guice outsid&#8230;
</p>
</li>
<li>
<p>
Use Guice to create the per-request GerritCall object
</p>
</li>
<li>
<p>
RegisterNewEmailSender is managed by Guice through Ass&#8230;
</p>
</li>
<li>
<p>
AddReviewerSender class is managed by Guice through As&#8230;
</p>
</li>
<li>
<p>
Merge change 10856
</p>
</li>
<li>
<p>
Merge change 10858
</p>
</li>
<li>
<p>
FilebasedConfig requires File pointing at config file &#8230;
</p>
</li>
<li>
<p>
CreateChangeSender class is managed by Guice through A&#8230;
</p>
</li>
<li>
<p>
AbandonedSender is managed by Guice now.
</p>
</li>
<li>
<p>
Move RegisterNewEmailSender to servlet module
</p>
</li>
<li>
<p>
Move authentication bits out of GerritServer
</p>
</li>
<li>
<p>
Update Ehcache to 1.6.1
</p>
</li>
<li>
<p>
Move Ehcache construction out of GerritServer to Guice
</p>
</li>
<li>
<p>
CommentSender is managed by Guice now.
</p>
</li>
<li>
<p>
MergedSender class is managed by Guice now.
</p>
</li>
<li>
<p>
MergeFailSender is managed by Guice now.
</p>
</li>
<li>
<p>
Make ReplacePatchSetSender managed by Guice.
</p>
</li>
<li>
<p>
Refactor MergeOp to use assisted injection
</p>
</li>
<li>
<p>
Inject the canonicalweburl rather than using GerritSer&#8230;
</p>
</li>
<li>
<p>
Use JGit&#8217;s cached hostname when URL can&#8217;t give us the &#8230;
</p>
</li>
<li>
<p>
Remove use of PatchSetInfoAccess interface in PatchDet&#8230;
</p>
</li>
<li>
<p>
Merge change 10839
</p>
</li>
<li>
<p>
Use member injection for OutgoingEmail related depende&#8230;
</p>
</li>
<li>
<p>
Fix CanonicalWebUrl when it is null
</p>
</li>
<li>
<p>
Inject the Provider GerritCall rather than looking it&#8230;
</p>
</li>
<li>
<p>
Use assisted injection to create the PushOp instances
</p>
</li>
<li>
<p>
Use PatchSetInfoFactory in OutgoingEmail class.
</p>
</li>
<li>
<p>
Simplify the setup of assisted injection factories
</p>
</li>
<li>
<p>
Inject the WorkQueue via Guice
</p>
</li>
<li>
<p>
Fix ProvisionException catch blocks in GerritServletCo&#8230;
</p>
</li>
<li>
<p>
Move system configuration related code to the server.c&#8230;
</p>
</li>
<li>
<p>
Move servlets related to UI RPCs into the server.rpc p&#8230;
</p>
</li>
<li>
<p>
Reduce CreateSchema dependencies to avoid cache
</p>
</li>
<li>
<p>
Start injectors in production mode
</p>
</li>
<li>
<p>
Isolate SSHD module from web module
</p>
</li>
<li>
<p>
Use ServletContext injection to load files from context
</p>
</li>
<li>
<p>
Refactor SSH commands into their own package
</p>
</li>
<li>
<p>
Support Guice request and session scopes in SSHD
</p>
</li>
<li>
<p>
Cleanup CommandFactory to be session aware
</p>
</li>
<li>
<p>
Refactor CurrentUser to always be request scoped
</p>
</li>
<li>
<p>
Cleanup names of SSH daemon related classes
</p>
</li>
<li>
<p>
Refactor command handling to support subcommands in Gu&#8230;
</p>
</li>
<li>
<p>
Refactor command thread creation logic into BaseCommand
</p>
</li>
<li>
<p>
Move command line parsing to BaseCommand
</p>
</li>
<li>
<p>
Avoid duplicate singletons
</p>
</li>
<li>
<p>
Don&#8217;t inject fields in providers
</p>
</li>
<li>
<p>
Run Gerrit servlet container in PRODUCTION mode
</p>
</li>
<li>
<p>
Make database error reporting more predictable from th&#8230;
</p>
</li>
<li>
<p>
Fix duplicate definition of ReviewDb injection
</p>
</li>
<li>
<p>
Cleanup unused imports in client code
</p>
</li>
<li>
<p>
Remove unnecessary references to HttpServletRequest
</p>
</li>
<li>
<p>
Get HttpServletRequest via injection rather than JsonS&#8230;
</p>
</li>
<li>
<p>
Get the remote peer address via the @RemotePeer annota&#8230;
</p>
</li>
<li>
<p>
Move HTTP related classes to an HTTP specific package
</p>
</li>
<li>
<p>
Drop ServletName in favor a unique annotation object
</p>
</li>
<li>
<p>
Move all URL lookup to the CanonicalUrlProvider
</p>
</li>
<li>
<p>
Only load the OpenID servlets if we are using OpenID a&#8230;
</p>
</li>
<li>
<p>
Make the magic "Become" mode for development a normal &#8230;
</p>
</li>
<li>
<p>
Present new users with a registion welcome screen
</p>
</li>
<li>
<p>
Fix SSH daemon in web mode to actually have commands
</p>
</li>
<li>
<p>
Explicitly bind RemoteJsonService implementations to t&#8230;
</p>
</li>
<li>
<p>
Use Anchor for become rather than location assignment
</p>
</li>
<li>
<p>
Move the become any account form to a real HTML file
</p>
</li>
<li>
<p>
Document the DEVELOPMENT_BECOME_ANY_ACCOUNT auth.type &#8230;
</p>
</li>
<li>
<p>
Fix upgrade014_015_part1_mysql syntax errors
</p>
</li>
<li>
<p>
Merge change 10972
</p>
</li>
<li>
<p>
Inject most server references to GerritConfig
</p>
</li>
<li>
<p>
Cleanup CacheManagerProvider&#8217;s construction of the con&#8230;
</p>
</li>
<li>
<p>
Make DiffCacheEntryFactory package private
</p>
</li>
<li>
<p>
Cache account ids by email address key in Ehcache
</p>
</li>
<li>
<p>
Rename ReviewDbProvider to ReviewDbDatabaseProvider
</p>
</li>
<li>
<p>
Perform per-request cleanup actions at the end of a re&#8230;
</p>
</li>
<li>
<p>
Refactor ChangeDetailService to use injected database &#8230;
</p>
</li>
<li>
<p>
Move ChangeDetailService code to its own package
</p>
</li>
<li>
<p>
Refactor ChangeManageService to use the new Handler st&#8230;
</p>
</li>
<li>
<p>
Refactor SSH commands to use request scoped database h&#8230;
</p>
</li>
<li>
<p>
Fix docs in BaseCommand
</p>
</li>
<li>
<p>
Mark all of BaseServiceImplementation deprecated
</p>
</li>
<li>
<p>
Refactor SSH command permission checks to use CurrentU&#8230;
</p>
</li>
<li>
<p>
Move ProjectCache to server side and rewrite entire pe&#8230;
</p>
</li>
<li>
<p>
Make existing BaseServiceImplementation use per-reques&#8230;
</p>
</li>
<li>
<p>
Use Project.NameKey in admin panels rather than Projec&#8230;
</p>
</li>
<li>
<p>
Change project to use Project.NameKey as the primary k&#8230;
</p>
</li>
<li>
<p>
Fix sshdAddress in GerritConfig object sent to clients
</p>
</li>
<li>
<p>
Rename ProjectCache.invalidate to evict
</p>
</li>
<li>
<p>
Rename ChangeDetailModule to ChangeModule
</p>
</li>
<li>
<p>
Move account related RPCs to the account package
</p>
</li>
<li>
<p>
Move patch RPC stuff to the rpc.patch package
</p>
</li>
<li>
<p>
Remove unnecessary injected dependencies from CatServl&#8230;
</p>
</li>
<li>
<p>
Document why we abuse the GerritCall in HostPageServlet
</p>
</li>
<li>
<p>
Create a dummy account if the user account no longer e&#8230;
</p>
</li>
<li>
<p>
Construct the AgreementInfo only from server code
</p>
</li>
<li>
<p>
Merge change 11021
</p>
</li>
<li>
<p>
Convert GroupCache to be injected by Guice and stored &#8230;
</p>
</li>
<li>
<p>
Remove Common.getAccountId and use Guice injection only
</p>
</li>
<li>
<p>
Remove Common.getSchemaFactory
</p>
</li>
<li>
<p>
Remove Common.getAccountCache
</p>
</li>
<li>
<p>
Consolidate account lookups to the AccountResolver
</p>
</li>
<li>
<p>
Rename GerritServerModule to GerritGlobalModule
</p>
</li>
<li>
<p>
Rename SshDaemonModule to SshModule
</p>
</li>
<li>
<p>
Update documentation on the named caches
</p>
</li>
<li>
<p>
Move trusted_external_ids to auth.trustedOpenID
</p>
</li>
<li>
<p>
Paper bag fix OutgoingEmail initialization
</p>
</li>
<li>
<p>
Paper bag fix submit action
</p>
</li>
<li>
<p>
Fix server error <em>Array index out of range</em> on some pa&#8230;
</p>
</li>
<li>
<p>
Merge branch <em>maint</em>
</p>
</li>
<li>
<p>
Move ChangeApproval to be a child of PatchSet
</p>
</li>
<li>
<p>
Make #register alone go to the registration form
</p>
</li>
<li>
<p>
Enable register new email after saving contact informa&#8230;
</p>
</li>
<li>
<p>
Bind ApprovalTypes without using GerritConfig
</p>
</li>
<li>
<p>
Remove Common class entirely
</p>
</li>
<li>
<p>
Catch missing BouncyCastle PGP during contact store cr&#8230;
</p>
</li>
<li>
<p>
Correct Owner project_rights min_values during upgrade
</p>
</li>
<li>
<p>
Unset use_contributor_agreements if agreements are dis&#8230;
</p>
</li>
<li>
<p>
Sort permissions in project access tab
</p>
</li>
<li>
<p>
Get branches directly from Git rather than database
</p>
</li>
<li>
<p>
Style tab panel headers like our menu bar header
</p>
</li>
<li>
<p>
Narrow tables that don&#8217;t have to be 100% width
</p>
</li>
<li>
<p>
Cleanup display of external ids in the user settings
</p>
</li>
<li>
<p>
Preserve negative approvals when replacing patch sets
</p>
</li>
<li>
<p>
Use gwtjsonrpc 1.1.1
</p>
</li>
<li>
<p>
gerrit 2.0.18
</p>
</li>
</ul></div>
</div>
</div>
</div>
<div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
Version 2.0.18 (from v2.7-rc0-149-g3be717b)<br />
Last updated 2013-10-08 10:02:12 PDT
</div>
</div>
</body>
</html>
